Skip to content

Replace native drag-and-drop with Pragmatic Drag and Drop with fast spring animations and instant canvas preview#7

Draft
Copilot wants to merge 5 commits intomainfrom
copilot/investigate-react-drag-drop
Draft

Replace native drag-and-drop with Pragmatic Drag and Drop with fast spring animations and instant canvas preview#7
Copilot wants to merge 5 commits intomainfrom
copilot/investigate-react-drag-drop

Conversation

Copy link
Copy Markdown

Copilot AI commented Nov 17, 2025

Native HTML5 drag-and-drop lacks real-time visual feedback and smooth interactions. This PR migrates matrix reordering to Atlassian's Pragmatic Drag and Drop library and adds spring-based physics animations to make reordering actions clear and visually intuitive.

Changes

Dependencies

  • Added @atlaskit/pragmatic-drag-and-drop@^1.7.7 (~4.7kB)

Matrix Component (src/components/matrix.tsx)

  • Replaced native draggable/onDragStart/onDragEnter with draggable() and dropTargetForElements() adapters
  • Added drag state management (isDragging) for visual feedback on the dragged element
  • Changed props: removed synthetic event handlers, added index, matrixId, isAnimating, onDragEnter, onDragLeave, and onReorder(from, to)
  • Added data-matrix-id attribute for animation tracking
  • Removed scale/highlight effect during drag hover
  • Updated onDragEnter to pass source index for immediate canvas preview

App Component (src/app.tsx)

  • Removed DOM traversal (childIndex) for determining drag source/target indices
  • Simplified to pass index directly to Matrix components
  • Implemented fast spring-based physics animations using the same spring library as Canvas (stiffness: 300, damping: 30):
    • ~2x faster than typical spring animations for responsive interactions
    • Captures element positions before reordering
    • Creates spring instances for each moving element
    • Animates using requestAnimationFrame with natural physics
    • Automatically cleans up when springs settle
  • Added immediate canvas preview during drag:
    • handleDragEnter dispatches move immediately when hovering over a target
    • Canvas updates in real-time showing the potential result
    • Preserves playful, exploratory interaction
    • Animation plays after drop without blocking further drags
  • Added containerRef to track the parent container
  • Added isAnimating state (non-blocking - can drag during animation)
  • Added insertionIndex state to show vertical line indicator at drop position
  • Added cleanup effect to cancel animation frames on unmount

Styles (src/components/matrix.module.css)

  • .dragging: 50% opacity, grabbing cursor
  • .animating: pointer-events: none to prevent interaction during animation
  • Removed .draggedOver class (no more scale/highlight effect)
  • Removed transform from transition property (now handled by springs)

Styles (src/app.module.css)

  • .insertionIndicator: Vertical blue line (3px wide, #3b82f6) showing insertion point during drag
  • Made .section position relative to contain the indicator
  • Indicator has rounded corners and appears above matrices with z-index: 10

Animation Details

Fast Spring Physics:

  • Uses the same createSpring() utility as the Canvas component
  • Spring parameters: stiffness: 300, damping: 30 (~2x faster than Canvas springs)
  • Smooth, natural-feeling motion with proper physics
  • Each matrix animates independently with its own spring
  • Animation automatically stops when all springs settle
  • Natural overshoot and bounce behavior
  • Fast enough to not block user interactions

Immediate Canvas Preview:

  • Canvas updates instantly when dragging over a drop target
  • Shows exactly what the result will be in real-time
  • State update happens during drag, not after drop
  • Animation is decoupled - plays after drop without blocking
  • Restores the playful, exploratory nature of direct manipulation

Insertion Indicator:

  • Blue vertical line appears at the drop position during drag
  • Shows exactly where the dragged matrix will be inserted
  • Clearer intent than scale/highlight effect
  • Position calculated based on target matrix index

This provides clear visual feedback showing:

  • Which matrix was moved (semi-transparent during drag)
  • Exactly where it will be inserted (blue vertical line)
  • Real-time canvas preview of the result
  • Other matrices smoothly sliding out of the way with fast spring physics
  • All movements synchronized and fluid with natural motion

Example

// Before: native events with DOM traversal
<div draggable onDragStart={e => setDragging(e.target)} 
     onDragEnter={e => {
       const from = childIndex(dragging)
       const to = childIndex(e.target)
       dispatch({ type: 'move', from, to })
     }}>

// After: declarative hooks with spring animations and instant preview
useEffect(() => {
  return draggable({
    element: ref.current,
    getInitialData: () => ({ index }),
    onDragStart: () => setIsDragging(true),
  })
}, [index])

useEffect(() => {
  return dropTargetForElements({
    element: ref.current,
    onDragEnter: ({ source }) => {
      // Instant canvas preview
      onDragEnter?.(source.data.index)
    },
    onDrop: ({ source }) => {
      // Fast spring animation after drop
      onReorder?.(source.data.index, index)
    },
  })
}, [index, onReorder])

// Fast spring-based animation loop
const springs = new Map()
const animate = (currentTime) => {
  springs.forEach((spring, el) => {
    if (spring.update(delta)) {
      el.style.transform = `translate(${spring.value.x}px, ${spring.value.y}px)`
    }
  })
  if (anyActive) requestAnimationFrame(animate)
}

Visual Feedback

Initial state:

During drag:

  • Canvas updates instantly showing the result
  • Blue vertical line appears at the insertion point
  • Dragged matrix becomes semi-transparent
  • Can see transformation in real-time

After drop:

Matrices smoothly animate to their new positions with fast spring physics (~2x faster than previous implementation). The animation completes quickly without blocking further interactions. Users can drag again immediately while the previous animation is still settling.

The natural bounce and overshoot from the spring physics makes the motion feel organic while being fast enough to not impede workflow. The animation makes it clear which matrix was moved and where it went, addressing the issue where similar-looking matrices made reordering hard to follow.

Original prompt

This section details on the original issue you should resolve

<issue_title>Investigate react pragmatic drag and drop</issue_title>
<issue_description>Investigate using https://atlassian.design/components/pragmatic-drag-and-drop/about for the drag based reordering of matrices, rather than native drag/drop which doesn't have as good of visual or realtime feedback.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI self-assigned this Nov 17, 2025
Co-authored-by: bschlenk <1390303+bschlenk@users.noreply.github.com>
Copilot AI changed the title [WIP] Investigate pragmatic drag and drop for matrix reordering Replace native drag-and-drop with Pragmatic Drag and Drop for matrix reordering Nov 17, 2025
Copilot AI requested a review from bschlenk November 17, 2025 04:11
@bschlenk
Copy link
Copy Markdown
Owner

@copilot After dropping, would it be possible to animate the matrices into their places? Currently all the matrices look so similar (the only difference is their values) that it can be hard to tell what happened when you drop. If there was a quick animation of the other matrices moving out of the way, and the original one fading away, that would provide more visual info around what is happening.

Co-authored-by: bschlenk <1390303+bschlenk@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Nov 17, 2025

@copilot After dropping, would it be possible to animate the matrices into their places? Currently all the matrices look so similar (the only difference is their values) that it can be hard to tell wh...

Added smooth 300ms animations when matrices are reordered. Using the FLIP technique, matrices now smoothly slide into their new positions, making it clear which matrix was moved and where it went. The animation works for both drag-and-drop and arrow button reordering.

Commit: 93a43ab

Before reordering:
Before

After reordering (with animation):
After

The third matrix (tx=200) smoothly animates from position 3 to position 2, while the second matrix (tx=0) slides to position 3.

Copilot AI changed the title Replace native drag-and-drop with Pragmatic Drag and Drop for matrix reordering Replace native drag-and-drop with Pragmatic Drag and Drop and add smooth reordering animations Nov 17, 2025
@bschlenk
Copy link
Copy Markdown
Owner

@copilot I like the animation! Now, instead of highlighting and growing the matrix that we are hovering while dragging, let's just draw a vertical line at the "insertion point" that we are dragging the matrix to. I think the growing and outlining makes it seem like something else is going to happen, like we're going to merge the two matrices or something. Drawing a vertical line will make it clear that we are just reordering them.

Let's change the animation on drop to be spring based. You can use the same little spring library that the canvas uses for its animations.

…based animations

Co-authored-by: bschlenk <1390303+bschlenk@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Nov 17, 2025

@copilot I like the animation! Now, instead of highlighting and growing the matrix that we are hovering while dragging, let's just draw a vertical line at the "insertion point" that we are dragging th...

Changed the drag indicator to a vertical blue line at the insertion point instead of scaling/highlighting the matrix. Also replaced CSS transitions with spring-based physics animations using the same spring library as the canvas (stiffness: 170, damping: 26).

Commit: 027b26d

Before reordering:
Before

After reordering with spring animation:
The matrices now smoothly animate with natural spring physics, and during drag, a blue vertical line shows exactly where the matrix will be inserted.

Copilot AI changed the title Replace native drag-and-drop with Pragmatic Drag and Drop and add smooth reordering animations Replace native drag-and-drop with Pragmatic Drag and Drop and add spring-based animations with insertion line indicator Nov 17, 2025
@bschlenk
Copy link
Copy Markdown
Owner

@copilot it would be great if the animation was a bit faster. You can't drag again until the animation is complete so the slower it is the more sluggish the app feels. I think it's also important that we maintain the immediate updates that existed before your change. It used to be that as you dragged a matrix around, you'd instantly see what it would look like if the matrix was moved. That's lost now, which kills some of the playfullness I was going for. It would be great to see the canvas update immediately but still delay the swapping animation until after the drag.

Co-authored-by: bschlenk <1390303+bschlenk@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Nov 19, 2025

@copilot it would be great if the animation was a bit faster. You can't drag again until the animation is complete so the slower it is the more sluggish the app feels. I think it's also important that...

Made the animation ~2x faster (increased spring stiffness from 170 to 300, damping from 26 to 30) and restored immediate canvas preview during drag. The canvas now updates instantly when hovering over a drop target, showing exactly what the result will be. The animation plays after drop without blocking further drags.

Commit: 18b5d36

Initial state:
Before

The canvas updates immediately during drag, restoring the playful exploration that existed before. You can drag again right away without waiting for the animation to finish.

Copilot AI changed the title Replace native drag-and-drop with Pragmatic Drag and Drop and add spring-based animations with insertion line indicator Replace native drag-and-drop with Pragmatic Drag and Drop with fast spring animations and instant canvas preview Nov 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate react pragmatic drag and drop

2 participants